package com.moro.lisp.closure;

import java.util.ArrayList;
import java.util.List;

import com.moro.lisp.JLispData;
import com.moro.lisp.JLispType;
import com.moro.lisp.tools.JLispStack;
import com.moro.lisp.typedefine.Atom;
import com.moro.lisp.typedefine.Error;

/**
 * 该类表示闭包中的作用域类，注意只有在
 * 闭包中作用域才有意义，因为如果不是闭包
 * 的话作用域的问题可以直接用栈这种数据结
 * 构去解决，而闭包可以将作用域保存起来
 * @author HJ
 *
 */
public class Action {
	
	
	
	/*
	 * 该作用域所归属的值栈
	 */
	public JLispStack jLispStack;
	
	
	/*
	 * 一个符号的某个值会产生一个作用域，该字段表示这个值，注意一旦作用域产生并且不再是当前作用域的话便不再和那个符号拥有联系，两者是相互独立的
	 */
	public JLispData value;
	
	
	/*
	 * 这个字段表示该作用域由符号的哪一层的一般值所定义的
	 */
	public int indexOfSymbolValue; 
	
	
	/*
	 * 这个字段表示与该作用域所绑定的函数或者宏
	 */
	public List<JLispData> bindingFunctionOrMacro;
	
	
	
	/*
	 * 这个字段表示该作用域当前的状态
	 */
	public ActionStatus status;
	
	
	
	public Action(JLispStack jLispStack, JLispData value,int indexOfSymbolValue) {
		this.jLispStack = jLispStack;
		this.value = value;
		this.indexOfSymbolValue = indexOfSymbolValue;
		this.bindingFunctionOrMacro = new ArrayList<JLispData>();
		this.status = ActionStatus.NOWACTION;
	}
	
	
	public void addFunctionOrMacro(JLispData functionOrMacro) {
		this.bindingFunctionOrMacro.add(functionOrMacro);
	}
	
	public boolean removeFunctionOrMacro(JLispData functionOrMacro) {
		for(int i = 0;i < this.bindingFunctionOrMacro.size();i++) {
			if(this.bindingFunctionOrMacro.get(i).data == functionOrMacro.data) {
				this.bindingFunctionOrMacro.remove(this.bindingFunctionOrMacro.get(i));
				return true;
			}
		}
		return false;
	}
	public void setValue(JLispData value) {
		
		if(ActionStatus.ALONE != this.status) {
			this.jLispStack.resetValById(value, this.indexOfSymbolValue);
			this.value = this.jLispStack.getValById(this.indexOfSymbolValue);
		}else {
			if(value.type == JLispType.MACRO) {//如果值是Macro则直接返回不作任何操作
				new Error("The macro can not be closure's value");
				return;
			}
			this.value = value;
		}
	}
}
